// Copyright (c) 2013-2013,  6932401@qq.com
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or 
// without modification, are permitted provided that the 
// following conditions are met.
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above 
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials 
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


#ifndef __LIGHT_CONTROL_H___
#define __LIGHT_CONTROL_H___

#include <Windows.h>
#include <objidl.h>
#include <GdiPlus.h>
#include <string>
#include <vector>

#define WM_UICLICK   (WM_USER + 0x100)
#define SAFE_FREE_OBJECT(x) { if (x) delete x; x = NULL;}
#define SAFE_FREE_ARRAY(x)  { if (x) delete []x; x = NULL;}
#define SAFE_DELTE_OBJECT(x) { if (x) ::DeleteObject(x); x = NULL;}


inline void PARAM2POINT(LPARAM lParam, POINT &pt)
{
	pt.y = (lParam & 0xFFFF0000) >> 16;
	pt.x = (lParam & 0x0000FFFF);
}

enum  CONTROL_STATE
{
	CONTROL_STATE_NORMAL,  //ÆÕÍ¨
	CONTROL_STATE_DOWN,    
	CONTROL_STATE_HIGH,
	CONTROL_STATE_SELECT,
	CONTROL_STATE_GRAY,
	
}; 
enum MOUSE_SHIFT_STATE
{
	MOUSE_SHIFT_MOVE,
	MOUSE_SHIFT_LDOWN,
	MOUSE_SHIFT_LUP
};
 
class CControlUI
{
public:
	explicit CControlUI(HWND hOnwer);
	virtual ~CControlUI() {};
public:
	virtual void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint) = 0;
	virtual BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	virtual void SetItem(int x, int y, int w, int h);
	virtual void SetVisible(BOOL bVisible);
	virtual void SetEnable(BOOL bEnabled);
	virtual void SetText(LPCWSTR lpstrText);
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
	virtual LPCWSTR GetText();
	virtual void SetBtnId(int iBtnId);
	Gdiplus::Rect GetPos();
	BOOL IsVisible();
	BOOL IsEnable();
	void Invalidate();
	HWND GetOwner();
	static BOOL GetEncoderClsid(const WCHAR* format, CLSID* pClsid);
protected:
	Gdiplus::Rect m_rcItem;
	BOOL m_bVisible;
	BOOL m_bEnabled;
	HWND m_hOwner;
};

class CResButton : public CControlUI
{
public: 
	explicit CResButton(HINSTANCE hInst, LPCWSTR lpItem, HWND hOwner, int iBtnId, DWORD dwResNormal, DWORD dwResDown, 
		DWORD dwResHigh, DWORD dwResGray);
	~CResButton();
public:
	BOOL ReCreateBtnImage(HINSTANCE hInst, LPCWSTR lpItem, DWORD dwResNormal, DWORD dwResDown, 
		DWORD dwResHigh, DWORD dwResGray);
	BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
	void SetEnable(BOOL bEnabled); 
	void SetText(LPCWSTR lpstrText);
	void SetFont(LPCWSTR lpFontName, int nSize, COLORREF clr);
	void SetFontStyle(BOOL bBold);
	virtual void OnClick(const POINT &pt);
	void SetBtnId(int iBtnId);
private:
	CONTROL_STATE m_State;
	void SetButtonState(CONTROL_STATE dwState);
private:
	Gdiplus::Image *m_pNormal;
	Gdiplus::Image *m_pDown;
	Gdiplus::Image *m_pHigh;
	Gdiplus::Image *m_pGray;
	Gdiplus::Font  *m_pFont;
	Gdiplus::SolidBrush *m_pBrush;
	Gdiplus::StringFormat m_strFormat;
   
	LPWSTR m_lpstrText;
	BOOL m_bDown;
	int  m_iBtnId;
};

class CResProgress : public CControlUI
{
public:
	explicit CResProgress(HINSTANCE hInst, LPCWSTR lpItem, HWND hOwner, DWORD dwResBg, DWORD dwResFg);
	~CResProgress();
public:
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);  
	void SetMaxValue(int iMin, int iMax);
	void SetPos(int iPos);
    void SetShowPercent(BOOL bShow);
private:
	void DrawProgress(Gdiplus::Graphics &g, Gdiplus::Image *pImage, const Gdiplus::Rect &rc);
private:
	Gdiplus::Image *m_pBG;
	Gdiplus::Image *m_pFG;
    Gdiplus::Font  *m_pFont;
	Gdiplus::Brush *m_pBr;
	Gdiplus::StringFormat m_strFormat;

	BOOL m_bShowPercent;
	int  m_iMin;
	int  m_iMax;
	int  m_iPos;
};

class CLabelUI :public CControlUI
{
public:
	explicit CLabelUI(HWND hOwner);
	~CLabelUI();
public:
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint); 
	void SetText(LPCWSTR lpstr);
    LPCWSTR GetText();
	virtual void SetFont(LPCWSTR lpFontName, int nSize, COLORREF clr);
	void SetAlpha(BOOL bAlpha); 
    void SetBold(BOOL bBold);
    void SetTextAlign(int nAlign);
protected:
	Gdiplus::Font *m_pFont;
	Gdiplus::SolidBrush *m_pBrush; 	
    Gdiplus::StringFormat m_strFormat;
private:
    int m_nTextAlign;
	LPWSTR m_pText;
	BOOL m_bAlpha;
};

class CUrlLabelUI : public CLabelUI
{
public:
	explicit CUrlLabelUI(HWND hOwner);
	~CUrlLabelUI();
public:
	void AddText(LPCWSTR lpstrText, LPCWSTR lpstrUrl);
	BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
    void SetFont(LPCWSTR lpFontName, int nSize, COLORREF clr);
private:
	BOOL m_bDown;
    BOOL m_bMouseEnter;
	std::wstring m_strUrl;
};

//¶àÐÐÎÄ±¾
class CMemoLableUI: public CLabelUI
{
public:
	explicit CMemoLableUI(HWND hOwner);
	~CMemoLableUI();
public:
	virtual void SetText(LPCWSTR lpstrText);
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint); 
	void SetRowDistance(int iPixel);
	void SetFont(LPCWSTR lpFontName, int nSize, COLORREF clr);
private:
	std::vector<std::wstring> m_StringList;
	int m_nRowDistance; 
};

class CImageUI :public CControlUI
{
public:
	explicit CImageUI(HINSTANCE hInst, LPCWSTR lpItem, HWND hOwner, DWORD dwResImage);
	~CImageUI();
public:
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
private:
	Gdiplus::Image *m_pImage; 
};

class CResRadio :public CControlUI
{
public:
	explicit CResRadio(HINSTANCE hInst, LPCWSTR lpItem, HWND hOwner, DWORD dwNormalImage,
		DWORD dwHighImage, DWORD dwSelImage, DWORD dwSelHigh, DWORD dwGrayImage);
	~CResRadio();
public:
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
	BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	void OnSelChanged(const POINT &pt);
	void SetButtonState(CONTROL_STATE csState);
private:
	Gdiplus::Image *m_pNormalImage;
	Gdiplus::Image *m_pHighImage;
	Gdiplus::Image *m_pSelImage;
	Gdiplus::Image *m_pSelHighImage;
	Gdiplus::Image *m_pGrayImage;
	LPWSTR m_pText;
	Gdiplus::Font *m_pFont;
	Gdiplus::Brush *m_pBr;
	BOOL m_bDown;
	BOOL m_bSelected;
	CONTROL_STATE m_csState;
};

class CListItemUI :public CControlUI
{
public:
	explicit CListItemUI(HWND hOwner);
	~CListItemUI();
public:
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
	BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	void SetListItem(LPCWSTR lpstrTitle, LPCWSTR lpstrDateTime, LPCWSTR lpstrContent);
private:
    LPWSTR m_pTitle;
	LPWSTR m_pDateTime;
	LPWSTR m_pContent;
};

class CEditUI : public CControlUI
{
public:
	explicit CEditUI(HWND hOwner);
	~CEditUI();
public:
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
	BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	void SetText(LPCWSTR lpstrText);
	LPCWSTR GetText();
private:
	LPWSTR m_pText;
	HWND m_hEditWnd;
};

//
class CContainerUI :public CControlUI
{
public:
	explicit CContainerUI(HWND hOwner);
	~CContainerUI();
public:
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
	BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	void AddControl(CControlUI *pUI);
	void RemoveControl(CControlUI *pUI);
private:
	std::vector<CControlUI *> m_List;
};

class CTabUI : public CControlUI
{
public:
	explicit CTabUI(HINSTANCE hInst, LPCWSTR lpItem, HWND hOwner, DWORD dwResBk, DWORD dwResHot);
	~CTabUI();
public:
	void AddTabItem(LPCWSTR lpstrTabText, LPCWSTR lpstrUrl);
	BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
	void SetFont(LPCWSTR lpFontName, int nSize, COLORREF clr, BOOL bBold);
private:
	void SetTabHot(int Idx);
private:
	std::vector<std::wstring> m_TextList;
    std::vector<std::wstring> m_UrlList;
	int m_iHotTab;
	BOOL m_bDown;
	Gdiplus::StringFormat m_strFormat;
	Gdiplus::Font *m_pFont;
	Gdiplus::SolidBrush *m_pBrush;
	Gdiplus::Image *m_pTabBk;
	Gdiplus::Image *m_pTabHot;
};

class CImageList: public CControlUI
{
public:
	explicit CImageList(HINSTANCE hInst, LPCWSTR lpItem, HWND hOwner, DWORD dwRadioNor, 
                        DWORD dwRadioSel, DWORD dwCoverBk);
	~CImageList();
public:
	void AddImage(HINSTANCE hInst, LPCWSTR lpItem, DWORD dwResId, LPCWSTR lpstrUrl);
	void NextImage();
    void PrevImage();
    void SetSelImage(int Idx);
    BOOL MouseInButton(const POINT &pt, MOUSE_SHIFT_STATE dwShiftState);
	void Draw(Gdiplus::Graphics &g, const Gdiplus::Rect &rcPaint);
private:
	std::vector<Gdiplus::Image *> m_ImageList;
	std::vector<std::wstring> m_UrlList;
	Gdiplus::Image *m_pRadioNor;
	Gdiplus::Image *m_pRadioSel;
    Gdiplus::Image *m_pCoverBk;
    int m_CurrIdx;
    BOOL m_bDown;
};

class CWindowWnd
{
public:
	CWindowWnd();
	virtual ~CWindowWnd();
public:
	BOOL Show(BOOL bShow);	
	void Close();
	HWND Create(HINSTANCE hInst, HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, const RECT rc, HMENU hMenu = NULL);
    HWND Create(HINSTANCE hInst, HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, 
		int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT, HMENU hMenu = NULL);
    HWND GetWnd();
protected:	
	BOOL RegisterWindow(HINSTANCE hInst, HICON hICon);
	static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam); 
	virtual void OnFinalMessage(HWND hWnd);
	virtual LPCTSTR GetWindowClassName();

protected:	
	HWND m_hWnd;	
};

 
#endif
